package com.vehicle.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.vehicle.bean.Area;
import com.vehicle.form.SuggestForm;
import com.vehicle.mapper.AreaMapper;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@RestController
@RequestMapping("/my-park")
public class TuiJianController {

    @Autowired
    AreaMapper areaMapper;

    @PostMapping("/recommend")
    public List<ParkingLocation> recommendParking(@RequestBody SuggestForm suggestForm) {
        System.out.println("获取到的数据如下：");
        System.out.println(suggestForm);
        // 获取用户的经纬度
        double userLatitude = Double.parseDouble(suggestForm.getLatitude());
        double userLongitude = Double.parseDouble(suggestForm.getLongitude());

        // 从数据库或缓存中获取停车场的经纬度和其他相关信息
        List<ParkingLocation> parkingLocations = getParkingLocations(suggestForm.getCategoryId());


        // 计算用户与停车场的距离
        calculateDistances(userLatitude, userLongitude, parkingLocations);

        // 根据安全性和容量对停车场进行打分
        rateParkingLocations(parkingLocations);

        //计算距离和评分的综合评分
        calculateAllScore(parkingLocations);
        // 根据打分排序停车场列表
        Collections.sort(parkingLocations);

        // 返回前端推荐的最佳停车位置
        return parkingLocations;
    }

    // 获取停车场的经纬度和其他相关信息，可以从数据库或缓存中获取
    private List<ParkingLocation> getParkingLocations(Integer categoryId) {
        // 示例代码，模拟从数据库或缓存中获取停车场信息
        List<ParkingLocation> parkingLocations = new ArrayList<>();
        QueryWrapper<Area> queryWrapper = new QueryWrapper<Area>();
        queryWrapper.eq("category_id",categoryId);
        //根据用户停车类型推荐
        List<Area> list = areaMapper.selectList(queryWrapper);
        for (Area a:list) {
            ParkingLocation parkingLocation = new ParkingLocation();
            parkingLocation.setId(a.getAreaId());
            parkingLocation.setLongitude(Double.parseDouble(a.getLongitude()));
            parkingLocation.setLatitude(Double.parseDouble(a.getLatitude()));
            parkingLocation.setName(a.getLocation());
            parkingLocation.setCameras(a.getCameras());
            parkingLocation.setLights(a.getLights());
            parkingLocation.setSecurityPersonnel(a.getSecurityPersonnel());
            parkingLocation.setCapacity(a.getParkingNumber());
            parkingLocation.setParked_cars(a.getParkingNumber()-a.getFreeNumber());
            parkingLocations.add(parkingLocation);
        }
        return parkingLocations;
    }

    // 计算用户与停车场的距离
    private void calculateDistances(double userLatitude, double userLongitude, List<ParkingLocation> parkingLocations) {
        for (ParkingLocation parkingLocation : parkingLocations) {
            double parkingLatitude = parkingLocation.getLatitude();
            double parkingLongitude = parkingLocation.getLongitude();
            // 使用距离计算公式计算用户与停车场的距离
            double distance = calculateDistance(userLatitude, userLongitude, parkingLatitude, parkingLongitude);
            parkingLocation.setDistance(distance);
        }
    }

    // 计算两点间的距离
    private double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        double earthRadius = 6371000; // 地球半径，单位：米

        // 将经纬度转换为弧度
        double radLat1 = Math.toRadians(lat1);
        double radLon1 = Math.toRadians(lon1);
        double radLat2 = Math.toRadians(lat2);
        double radLon2 = Math.toRadians(lon2);

        // 计算经纬度差值
        double dlon = radLon2 - radLon1;
        double dlat = radLat2 - radLat1;

        double dLat = Math.toRadians(lat2 - lat1);
        double dLon = Math.toRadians(lon2 - lon1);
        // 应用 Haversine 公式计算两点间距离
        double a = Math.pow(Math.sin(dlat / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(dlon / 2), 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double distance = earthRadius * c;
        return distance;
    }

    // 根据安全性和容量对停车场进行打分
    private void rateParkingLocations(List<ParkingLocation> parkingLocations) {
        for (ParkingLocation parkingLocation : parkingLocations) {
            double safetyScore = calculateSafetyScore(parkingLocation);
            double capacityScore = calculateCapacityScore(parkingLocation);
            double totalScore = safetyScore + capacityScore;
            parkingLocation.setScore(totalScore);
        }
    }

    // 计算停车场的安全性分数
    private double calculateSafetyScore(ParkingLocation parkingLocation) {
        int cameras = parkingLocation.getCameras();
        int lights = parkingLocation.getLights();
        int securityPersonnel = parkingLocation.getSecurityPersonnel();
        // 根据以上因素进行打分
        double ThreeScore = 0;
        if (cameras >= 5) {
            ThreeScore += 2;  // 监控设备数量达标，得分较高
        } else if (cameras >= 3) {
            ThreeScore += 1;  // 监控设备数量一般，得分一般
        }
        if (lights >= 10) {
            ThreeScore += 2;  // 照明设施数量达标，得分较高
        } else if (lights >= 5) {
            ThreeScore += 1;  // 照明设施数量一般，得分一般
        }
        if (securityPersonnel > 0) {
            ThreeScore += 2;  // 安保人员存在，得分较高
        }
        return ThreeScore;
    }

    // 计算停车场的容量分数
    private double calculateCapacityScore(ParkingLocation parkingLocation) {
        // 示例代码，根据实际情况编写容量评分逻辑
        int capacity = parkingLocation.getCapacity();
        int parkedCars = parkingLocation.getParked_cars();
        // 计算该停车场的可用容量比例
        double availableRatio = (double) (capacity - parkedCars) / capacity;
        // 根据可用容量比例计算该停车场的得分
        double capacityScore;
        if (availableRatio >= 0.8) {
            capacityScore = 5;// 容量充足，得分最高
        } else if (availableRatio >= 0.6) {
            capacityScore = 4; // 容量较多，得分较高
        } else if (availableRatio >= 0.4) {
            capacityScore = 3; // 容量一般，得分一般
        } else if (availableRatio >= 0.2) {
            capacityScore = 2; // 容量较少，得分较低
        } else {
            capacityScore = 1; // 容量不足，得分最低 }
        }
        return capacityScore;
    }

    private void calculateAllScore(List<ParkingLocation> parkingLocations) {
        for (ParkingLocation parkingLocation : parkingLocations) {
            double disScore;
            if(parkingLocation.getDistance()<=500){
                disScore = 5.0;
            }else if(parkingLocation.getDistance()<=100 && parkingLocation.getDistance()>500){
                disScore = 4.5;
            }else if(parkingLocation.getDistance()<=1500 && parkingLocation.getDistance()>1000){
                disScore = 4.0;
            }else {
                disScore = 3.5;
            }
            double all = disScore*0.6+parkingLocation.getScore()*0.4;
            parkingLocation.setAllScore(all);
        }
    }
}


@Data
class ParkingLocation implements Comparable<ParkingLocation> {
    private int id;
    private String name;
    private double latitude;
    private double longitude;
    private double distance;
    private double score;
    private int capacity;
    private Integer cameras;
    private Integer lights;
    private Integer parked_cars;
    private  Integer securityPersonnel;
    private double allScore;


    // 省略构造方法、getter和setter

    @Override
    public int compareTo(ParkingLocation other) {
        // 根据分数进行降序排序
        return Double.compare(other.score, this.score);
    }
}

